import {BleManager, Characteristic, Device} from 'react-native-ble-plx'; // 引入蓝牙模块
import {PermissionsAndroid, Platform} from 'react-native';
import { arrayBufferToBase64, string2buffer } from './common';
import { crc16 } from '../utils/crc';
import { BluetoothCommandCMDTypeEnum, BluetoothCtrlBikeCommandEnum } from '@/constants/BluetoothEnum';

// 授权(位置,蓝牙扫描,蓝牙连接三个权限,但是我这目前有一个问题,蓝牙连接和蓝牙扫描权限会重复弹出两次框,这个bug后期再改)
const bleManager = new BleManager();
// 位置信息和蓝牙权限信息(请求权限)
export const requestPermissions = async callback => {
  if (Platform.OS === 'ios') {
    return true;
  }
  if (
    Platform.OS === 'android' &&
    PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION
  ) {
    const apiLevel = parseInt(Platform.Version.toString(), 10);

    if (apiLevel < 31) {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
      );
      callback(granted === PermissionsAndroid.RESULTS.GRANTED)
    }
    if (
      PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN &&
      PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT
    ) {
      const result = await PermissionsAndroid.requestMultiple([
        PermissionsAndroid.PERMISSIONS.BLUETOOTH_SCAN,
        PermissionsAndroid.PERMISSIONS.BLUETOOTH_CONNECT,
        PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
      ]);

      callback(
        result['android.permission.BLUETOOTH_CONNECT'] ===
          PermissionsAndroid.RESULTS.GRANTED &&
          result['android.permission.BLUETOOTH_SCAN'] ===
            PermissionsAndroid.RESULTS.GRANTED &&
          result['android.permission.ACCESS_FINE_LOCATION'] ===
            PermissionsAndroid.RESULTS.GRANTED,
      );
      return
    }
  }

  this.showErrorToast('Permission have not been granted');
  callback(false);
};

// 扫描蓝牙设备
export const scanDevice = callback => {
  // 参数1可以为null不做限制,也可以为服务的uuid,例如['180D']:心率服务的uuid,这样就只扫描过滤出关于心率服务的设备的uuid,如下
  // bleManager.startDeviceScan(['180D'], null, (error, scannedDevice)
  bleManager.startDeviceScan(null, null, (error, scannedDevice) => {
    if (error) {
      console.error('扫描错误:', error);
      callback(ture, error);
      return;
    }
    console.log('scannedDevice', scannedDevice);
    callback(false, scannedDevice);
  });
};

// 返回信号强度(传入参数为上面的scannedDevice.rssi),每个数字都代表一个信号,我这就是0-5六个信号
export const BluetoothBatteryLevel = level => {
  let signal = 0;
  if (level < 0) {
    signal = Math.abs(level) / 10;
  } else {
    signal = 0;
  }
  if (signal > 0 && signal <= 3) {
    return 5;
  } else if (signal > 3 && signal <= 6) {
    return 4;
  } else if (signal > 6 && signal <= 9) {
    return 3;
  } else if (signal > 9 && signal <= 12) {
    return 2;
  } else if (signal > 12 && signal <= 15) {
    return 1;
  } else {
    return 0;
  }
};

// 断开某个连接的设备,传入的是scannedDevice.id设备编码,如E6:13:27:12:BF:92
export const disconnectAllDevices = async a => {
  try {
    if (bleManager) {
      await bleManager.cancelDeviceConnection(a);
    }
  } catch (error) {
    console.log('断开连接时出错:', error);
  }
};

// 连接蓝牙设备，然后自动发起手机号校验
export const connectAndDiscoverServices = async (device, callback) => {
  try {
    if (device) {
      bleManager.stopDeviceScan(); // 停止扫描
      device
        .connect() // 连接设备
        .then(device => {
          console.log('设备已连接:', device.id);
          return device.discoverAllServicesAndCharacteristics();
        })
        .then(device => {
          return device.services();
        })
        .then(services => {
          const service = services[0]
          const serviceId = service.uuid
          service.characteristics().then(characteristics => {
            const characteristic = characteristics[0]
            const characteristicId = characteristic.uuid
            console.log('设备characteristicId获取成功', characteristicId);
            updateBikeStatus(characteristic, BluetoothCtrlBikeCommandEnum.校验, (flag: boolean) => {
              if(flag) {
                console.log('校验成功')
                callback(true, characteristic)
              } else {
                callback(false)
              }
              // setTimeout(() => {
              //   updateBikeStatus(characteristic, 'engine', () => {
              //     console.log('启动成功')
              //   })
              // }, 200)
            })
          })
        })
        .catch(error => {
          console.error('连接设备出错:', error);
        });
    }
  } catch (error) {
    console.error('连接设备时出错:', error);
    return null;
  }
};

// 通过DeviceId连接蓝牙设备，然后自动发起手机号校验
export const connectToDeviceByDeviceId = async (deviceId: string, callback) => {
  try {
    if (deviceId) {
      bleManager.connectToDevice(deviceId)
      .then(device => {
        console.log('设备已连接:', device.id);
        return device.discoverAllServicesAndCharacteristics();
      })
      .then(device => {
        return device.services();
      })
      .then(services => {
        const service = services[0]
        const serviceId = service.uuid
        service.characteristics().then(characteristics => {
          const characteristic = characteristics[0]
          const characteristicId = characteristic.uuid
          console.log('设备characteristicId获取成功', characteristicId);
          updateBikeStatus(characteristic, BluetoothCtrlBikeCommandEnum.校验, (flag: boolean) => {
            if(flag) {
              console.log('校验成功')
              callback(true, characteristic)
            } else {
              callback(false)
            }
            // setTimeout(() => {
            //   updateBikeStatus(characteristic, 'engine', () => {
            //     console.log('启动成功')
            //   })
            // }, 200)
          })
        })
      })
      .catch(error => {
        console.error('连接设备出错:', error);
        callback(false)
      });
    }
  } catch (error) {
    console.error('连接设备时出错:', error);
    callback(false)
    return null;
  }
};

// 判断是否和DeviceId处于连接状态
export const isDeviceConnectedByDeviceId= async (deviceId: string, callback) => {
  const status = await bleManager.isDeviceConnected(deviceId)
  callback(status)
}

// 停止扫描
export const stopScan = () => {
  bleManager.stopDeviceScan();
};

// 断开连接
export const disconnectDevice =  async(deviceId: string, callback) => {
  // 断开连接
  await bleManager.cancelDeviceConnection(deviceId)
  .then(() => {
    console.log('设备已断开连接');
    callback(true)
  })
  .catch(error => {
    console.error('断开连接时发生错误:', error);
    callback(false)
  });
}
  // 连接断开监听
export const monitorDisConnect = (deviceId: string, callback) => {
  // 连接断开
  bleManager.onDeviceDisconnected(deviceId, (err) => {
    callback(err)
  })
}

// 控制车辆
export const updateBikeStatus = (characteristic: Characteristic, type: BluetoothCtrlBikeCommandEnum, callback: any) => {
  sendMsg(characteristic, type, (flag: boolean) => {
    console.log('操作成功')
    callback(flag)
  })
}
/** 组装发送数据*/
function setUpData(option:BluetoothCtrlBikeCommandEnum) {
  let resArr: Array<any> = [];
  // MAGIC字段
  resArr.push(78, 79);
  // CMD字段
  resArr.push(BluetoothCommandCMDTypeEnum[option])
  // Length字段
  if (option === 'mobile') {
    resArr.push('b');
    // data字段
    const mobile  = '18140662282'
    // console.log(mobile)
    try {
      resArr = resArr.concat(mobile.split('').map(item => {
        return Number(item)
      }));
    } catch (error) {

    }
  } else {
    resArr.push(0)
  }
  return resArr;
}

function sendMsg(characteristic: Characteristic, msgType: BluetoothCtrlBikeCommandEnum, callback: any) {
  const strArr = setUpData(msgType)
  console.log('strArr', strArr)
  const buffer = string2buffer(strArr)
  console.log('buffer', buffer)
  const crcStr = crc16(buffer) // 网上很多的 crc16 库不行。此处要注意
  console.log('crcStr', crcStr)
  strArr.push(crcStr.slice(0, 2))
  strArr.push(crcStr.slice(2, 4))
  console.log('strArr2', strArr)
  const newBuffer = string2buffer(strArr)
  console.log('newBuffer')
  console.log(newBuffer)
  // 微信小程序直接使用 buffer，expo 需要转 base64
  const paramsBase64 = arrayBufferToBase64(newBuffer)
  console.log('paramsBase64')      
  console.log(paramsBase64)
  characteristic.writeWithResponse(paramsBase64).then(res => {
    callback(true)
  }).catch(err => {
    console.log('校验失败',  err)
    callback(false)
  })
}
